package com.pc.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.ListUtils;
import com.pc.entity.*;
import com.pc.service.*;
import com.pc.utils.*;
import com.pc.utils.Excel.AddMoney;
import com.pc.utils.Excel.ExcelLogs;
import com.pc.utils.Excel.FoodSell;
import com.pc.utils.aop.OperLog;

import io.netty.util.concurrent.CompleteFuture;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;

@RestController
public class PcController {

    @Resource
    private MoneyService moneyService;

    @Resource
    private OrderStateService orderStateService;

    @Resource
    private OrderListService orderListService;

    @Resource
    private ChangemoneyService changemoneyService;

    @Resource
    private RedisService redisService;



    @Resource
    private UserlogService userlogService;

    @Resource
    private FoodService foodService;

    @Resource
    private UsersService usersService;

    @Autowired
    ThreadPoolTaskExecutor applicationTaskExecutor;

    //获得年,月,日已经完成的订单数
    @GetMapping("getOrderFinshed")
    @OperLog(operModul = "PC模块",operType = "订单",operDesc = "获得年月日的订单数")
    public Result getOrderFinshed(){
        int[] finshed = orderStateService.CountOrderFinshed();

        return Result.success("获得订单数成功1",finshed);

    }

    /**
     * 获得今天的订单状态
      */
    @GetMapping("CountOrderState")
    @OperLog(operModul = "PC模块",operType = "订单",operDesc = "今天的订单状态")
    public Result getCountOrderState(){
        int[] ints = orderStateService.CountOrderState();
        return Result.success("获取成功",ints);
    }

    /**
     * 得到卖的最好的六个商品
     */

    @GetMapping("getTopFood")
    @OperLog(operModul = "PC模块",operType = "图标可视化",operDesc = "查询卖的最好的10菜品")
    public Result getTopFoodName(){
        List<Topfood> topList = orderListService.getTopList();
        return Result.success("获取成功",topList);
    }
    /**
     * 获得卖的最差的十个产品
     */
    @GetMapping("getEndFood")
    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "获得卖的最差的十个商品")
    public Result getEndFoodName(){
        List<Topfood> endList = orderListService.getEndList();
        return Result.success("获取成功",endList);
    }

    /**
     * 得到12个月的营业额
     * 在充值的时候加过来,得到每个月的营业额
     * 再次得到每个月的已完成的订单数
     */
    @GetMapping("getMonthMoney")
    @OperLog(operModul = "PC模块",operType = "营业额",operDesc = "12个月的营业额")
    public Result getMonthMoney(){
        int[] monthMoney = changemoneyService.getMohtnMoney();
        int[] monthOrderFinsh = orderStateService.getMonthOrderFinsh();
        ArrayList<MonthOrder> monthOrders = new ArrayList<>();
        for (int i = 0; i < 12; i++) {
            MonthOrder monthOrder = new MonthOrder();
            monthOrder.setMonthMoney(String.valueOf(monthMoney[i]));
            monthOrder.setMonthOrder(String.valueOf(monthOrderFinsh[i]));
            monthOrders.add(monthOrder);
        }
        return Result.success("查寻成功",monthOrders);
    }
    /**
     * 得到充值前十的用户
     */
    @GetMapping("getTop10")
    @OperLog(operModul = "PC模块",operType = "充值",operDesc = "得到充值前十的用户")
    public Result getTop10(){
        List<Top10> top10 = changemoneyService.getTop10();
        return Result.success("查询成功",top10);
    }

    /**
     * 导出excel数据表处理 导出订单
     * @return
     */
    private List<FoodSell> getlistdata() {
        List<Orderstate> orderstates = orderStateService.exportExcelOrderState();
        List<FoodSell> list = ListUtils.newArrayList();
        for (int i = 0; i < orderstates.size(); i++) {
            FoodSell data = new FoodSell();
            data.setUsername(orderstates.get(i).getUsername());
            data.setDate(orderstates.get(i).getCreatedate());
            data.setUsermoney(orderstates.get(i).getMoney());
            list.add(data);
        }
        return list;
    }
    /**
     * 导出excel数据表处理 导出充值记录
     */
    private List<AddMoney> getAddMoney() {
        List<Changemoney> AddMoney = changemoneyService.exportexcelChangeMoney();
        List<AddMoney> list = ListUtils.newArrayList();
        for (int i = 0; i < AddMoney.size(); i++) {
            AddMoney data = new AddMoney();
            data.setUsername(AddMoney.get(i).getUsername());
            data.setDate(AddMoney.get(i).getCreatedate());
            data.setUsermoney(AddMoney.get(i).getAddmoney());
            list.add(data);
        }
        return list;
    }

    /**
     * 导出excel数据表处理 导出日志excel
     */

    private List<ExcelLogs> getListUserLog(){
        List<Userlog> allUserLog = userlogService.getAllUserLog();
        ArrayList<ExcelLogs> userlogs = ListUtils.newArrayList();
        for (int i = 0; i < allUserLog.size(); i++) {
            ExcelLogs excelLogs = new ExcelLogs();
            excelLogs.setUsername(allUserLog.get(i).getUsername());
            excelLogs.setModule(allUserLog.get(i).getModule());
            excelLogs.setType(allUserLog.get(i).getType());
            excelLogs.setDetail(allUserLog.get(i).getDetail());
            excelLogs.setDate(allUserLog.get(i).getDate());
            userlogs.add(excelLogs);
        }
        return userlogs;
    }
    /**
     * 导出excel 订单情况
     */
    @GetMapping("exportExcelFood")
    @OperLog(operModul = "PC模块",operType = "excel导出",operDesc = "导出订单详情excel")
    public void exportExccelFood(HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("点餐情况", "UTF-8").replaceAll("\\+", "%20");
        List<FoodSell> list = getlistdata();
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(),
                FoodSell.class).sheet("点餐情况").doWrite(list);

    }

    @GetMapping("exportExcelAddMoney")
    @OperLog(operModul = "PC模块",operType = "excel导出",operDesc = "导出充值详情excel")
    public void exportExccelAddMoney(HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("充值情况", "UTF-8").replaceAll("\\+", "%20");
        List<AddMoney> list = getAddMoney();
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(),
                AddMoney.class).sheet("充值情况").doWrite(list);

    }

    @GetMapping("exportExcelLogs")
    @OperLog(operModul = "PC模块",operType = "excel导出",operDesc = "导出操作日志")
    public void exportExcelOperLogs(HttpServletResponse response) throws IOException{
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("操作日志", "UTF-8").replaceAll("\\+", "%20");
        List<ExcelLogs> list = getListUserLog();
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(),
                ExcelLogs.class).sheet("充值情况").doWrite(list);
    }


    /**
     * @author 李林雨
     * @param request
     * @return ip地址
     * 如果一秒内该ip请求了五次，则封了他的ip
     */
    @GetMapping("testIp")
    public String testIp(HttpServletRequest request){
        String ipAddr = IPUtils.getIpAddr(request);
        redisService.setUserCode("ls","123456");
//        redisService.setIp(ipAddr);

//        redisUtils.set("restrictionIP",ipAddr);
//        System.out.println( "打印redis中存的"+redisUtils.get("restrictionIP"));

        return ipAddr;
    }

    @GetMapping("getRedisCode")
    @OperLog(operModul = "PC模块",operType = "redis",operDesc = "获取redis中的验证码")
    public String getRedisCode(){
        String ls = redisService.getUserCode("ls");
        return ls;
    }

//    @GetMapping("sendEmailCode")
//    @OperLog(operModul = "PC模块",operType = "email",operDesc = "发送验证码")
//    public String sendEmailCode(){
//        sendEmailService.sendMail("483653257@qq.com","邮箱验证码","123456");
//        return "发送调用成功";
//    }


    //上传图片接口
    @PostMapping("uploadimg")
    public Result fileUpload(@RequestPart("file")MultipartFile file){
//        String des ="/www/wwwroot/linyu.com/image/food/"+ file.getOriginalFilename();
        String des="D:\\"+file.getOriginalFilename();
        String[] split = des.split("\\.");
        if(split[1].equals("jpg") || split[1].equals("png") || split[1].equals("jpeg") || split[1].equals("bmp")){
            FileOutputStream fos = null;
            try {
                // 1. 获取输入流
                InputStream inputStream = file.getInputStream();
                // 2. 创建file
                File newFile = new File(des);
                // 3. 获取输出流
                fos = new FileOutputStream(newFile);
                // 4. 使用工具类进行写入
                IOUtils.copy(inputStream, fos);
            } catch (IOException e) {
                e.printStackTrace();
                Result.fail("上传失败");
            }finally {
                try {
                    fos.close(); // 记得关闭，不然文件写入可能不会完成。
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return Result.success("添加图片成功");
        }else{
            return Result.fail("图片格式不符合");
        }


    }

    //获得前10条的日志信息
    @GetMapping("getUserLogs")
    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "获得前10条日志")
    public Result getUserLogs(){
//        List<Userlog> list = userlogService.getAllUserLog();
        List<Userlog> userLogPage = userlogService.getUserLogPage(0);
        return Result.success("查询日志成功",userLogPage);
    }

    //根据用户姓名查询用户的操作
    @GetMapping("getLogByUsername/{username}")
    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "查询该用户的日志操作")
    public Result getLogByUsername(@PathVariable String username){
        List<Userlog> list = userlogService.getUserLogByUsername(username);
        if(list.size()>0)
            return Result.success("获取成功",list);
        else
            return Result.fail("查询失败，没有这个用户",list);
    }

    //分页显示日志
    @GetMapping("getLogBypage/{nowpage}")
    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "分页显示日志")
    public Result getLogBypage(@PathVariable int nowpage){
        List<Userlog> userLogPage = userlogService.getUserLogPage(nowpage);
        if(userLogPage.size()>0)
            return Result.success("查寻成功",userLogPage);
        else
            return Result.fail("查询失败");
    }

    //会获得所有food
    @GetMapping("getAllFood")
    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "获取所有食物清单")
    public Result getAllfood(){
        List<Food> allFood = foodService.getAllFood();
        return Result.success("获取全部食物成功",allFood);
    }

    //修改商品价格
    @GetMapping("modifyFoodPrice/{id}/{price}")
    @OperLog(operModul = "PC模块",operType = "修改",operDesc = "修改商品价格")
    public Result modifyFoodPrice(@PathVariable int id,@PathVariable int price){

        boolean b = foodService.modifyFoodPrice(id, price);
        if (b)
            return Result.success("更改价格成功");
        else
            return Result.fail("成功价格失败");
    }
    //根据商品名称查询
    @GetMapping("getFoodByName/{foodname}")
//    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "根据商品名称查询")
    public Result getFoodByName(@PathVariable String foodname){
        List<Food> foodByname = foodService.getFoodByname(foodname);
        if (foodByname.size()>0)
            return Result.success("查询成功",foodByname);
        else
            return Result.fail("没有这个商品");
    }

    //线程池测试
    @GetMapping("thread1")
    public Result thread1(){
        long start = System.currentTimeMillis();

        List<Food> allFood = foodService.getAllFood();
        List<Userlog> allUserLog = userlogService.getAllUserLog();

        long end = System.currentTimeMillis();
        ConcurrentHashMap<String, Object> hashMap = new ConcurrentHashMap<>();
        hashMap.put("time",(end-start));
        hashMap.put("data","就是数据");
        return Result.success("成功",hashMap);
    }

    @GetMapping("thread2")
    public Result thread2()  throws ExecutionException, InterruptedException{

        long start = System.currentTimeMillis();
        //异步执行
        CompletableFuture<Void> runAsync1 = CompletableFuture.runAsync(() -> {
            List<Food> allFood = foodService.getAllFood();
        }, applicationTaskExecutor);

        CompletableFuture<Void> runAsync2 = CompletableFuture.runAsync(() -> {
            List<Userlog> allUserLog = userlogService.getAllUserLog();
        }, applicationTaskExecutor);

        //等待完成
        CompletableFuture.allOf(runAsync1,runAsync2).get();

        long end = System.currentTimeMillis();
        Map<String, Object> map = new ConcurrentHashMap<>();
        map.put("time",(end-start));
        map.put("date","date");
        return Result.success("成功",map);
    }

    //获得所有用户数量
    @GetMapping("getUserNums")
    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "获得用户数量")
    public Result getUserNums(){
        List<Users> users = usersService.getUsers();
        if(users.size()>0)
            return Result.success("查询成功",users.size());
        else
            return Result.fail("查询失败");
    }

    //获得所有菜品数量
    @GetMapping("getFoodNums")
    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "获得菜品总量")
    public Result getFoodNums(){
        List<Food> food = foodService.getAllFood();
        if(food.size()>0)
            return Result.success("查询成功",food.size());
        else
            return Result.fail("查询失败");
    }

    //获得所有订单数量
    @GetMapping("getOrderNums")
    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "获得订单总量")
    public Result getOrderNums(){
        List<Orderlist> order = orderListService.getAllOrder();
        if(order.size()>0)
            return Result.success("查询成功",order.size());
        else
            return Result.fail("查询失败");
    }

    //得到所有用户的余额
    @GetMapping("getMoneyNums")
    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "获得营业额总量")
    public Result getAllMoney(){
        int allMoney = moneyService.getAllMoney();
        if(allMoney>0)
            return Result.success("查询成功",allMoney);
        else
            return Result.fail("查询失败");
    }

    //线程池优化店铺分析
    @GetMapping("getStoryByThread")
//    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "获得店铺优化线程池")
    public Result getStoryByThread() throws ExecutionException, InterruptedException {
        long start = System.currentTimeMillis();
        int story[]=new int[4];
        //开始异步
        //获得所有用户数量
        CompletableFuture<Void> runAsync1 = CompletableFuture.runAsync(() -> {
            List<Users> users = usersService.getUsers();
            story[0]=users.size();
        }, applicationTaskExecutor);
        //获得所有菜品数量
        CompletableFuture<Void> runAsync2 = CompletableFuture.runAsync(() -> {
            List<Food> food = foodService.getAllFood();
            story[1]=food.size();
        }, applicationTaskExecutor);
        //获得所有订单数量
        CompletableFuture<Void> runAsync3 = CompletableFuture.runAsync(() -> {
            List<Orderlist> order = orderListService.getAllOrder();
            story[2]=order.size();
        }, applicationTaskExecutor);
        //得到所有用户的余额
        CompletableFuture<Void> runAsync4 = CompletableFuture.runAsync(() -> {
            int allMoney = moneyService.getAllMoney();
            story[3]=allMoney;
        }, applicationTaskExecutor);
        //等待完成
        CompletableFuture.allOf(runAsync1,runAsync2,runAsync3,runAsync4).get();
        long end = System.currentTimeMillis();
        return Result.success(String.valueOf(end-start),story);
    }

    //店铺分析
    @GetMapping("getStory")
//    @OperLog(operModul = "PC模块",operType = "查询",operDesc = "获得店铺优化")
    public Result getStory() throws ExecutionException, InterruptedException {
        int story[]=new int[4];
        long start = System.currentTimeMillis();
        //开始异步
            List<Users> users = usersService.getUsers();
            story[0]=users.size();
        //获得所有菜品数量
            List<Food> food = foodService.getAllFood();
            story[1]=food.size();
        //获得所有订单数量
            List<Orderlist> order = orderListService.getAllOrder();
            story[2]=order.size();
        //得到所有用户的余额
            int allMoney = moneyService.getAllMoney();
            story[3]=allMoney;
        long end = System.currentTimeMillis();

        return Result.success(String.valueOf(end-start),story);
    }
}
